home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 744 / fo2 / sources_fo2 / fo.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  28KB  |  1,283 lines

  1. /*
  2. **        FO v1.3 by FBJ
  3. **      
  4. **      (c)Copyright 1991, Campagne Fabien, All Rights Reserved
  5. **
  6. **      Campagne Fabien
  7. **      805, Rue des Gentianes
  8. **      39000 Lons Le saunier
  9. **      FRANCE
  10. **
  11. **    un optimiseur de disk (rapide).
  12. **    FO doit être linké avec TD.o                                            
  13. **  pour compiler: cc FO "objects:TD.o -gs -r"                                    
  14. **  v1.3: a serious bug fixed (under 2.0, some files and dir will no longuer disappear)
  15. **                                                                        */
  16.  
  17. #include <exec/types.h>
  18. #include <exec/memory.h>
  19. #include <libraries/dos.h>
  20. #include <libraries/dosextens.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include "fbj/Blocks.h"
  24. #include "fbj/ShortBlocks.h"
  25. #include "fbj/TDprotos.h"
  26.  
  27.  
  28. /*#define DEBUG 1
  29. */
  30. #define ON 1L
  31. #define OFF 0L
  32. #define R CMD_READ
  33. #define W CMD_WRITE
  34. #define used 0
  35. #define var Variables
  36. #define BBM VarAdr->BuffBitMap
  37. /*#define BootB VarAdr->BuffTrack*/
  38. #define BT VarAdr->BuffTrack
  39. #define sourceDrive VarAdr->sourcedrive
  40. #define destDrive VarAdr->destdrive
  41. #define dsklist VarAdr->disklist
  42. #define CLI VarAdr->Cli
  43. #define err VarAdr->Err
  44. #define GFree VarAdr->GestFree
  45. #define DFree VarAdr->DataFree
  46. #define FLnog VarAdr->FLnoG
  47. #define drivebusy VarAdr->DriveBusy
  48. #define FORMAT VarAdr->Format
  49. #define CHECK VarAdr->Check
  50.  
  51. extern struct DosLibrary *DOSBase;
  52.  
  53. struct Variables{
  54.     LONG    *BuffBitMap;    /* adr du buffer contenant le bloc BitMap */
  55.     WORD    BitMap;        /* n° du Block BitMap */
  56.     LONG    *BuffTrack; /* Buffer de track pour le formattage de la destination */
  57.     LONG    *Empty;        /* pointeur sur zone contenant datas pour blocs vides */
  58.     BYTE    sourcedrive;    /* */
  59.     BYTE    destdrive;    /* */
  60.     LONG    TotalBlocks; /* */
  61.     LONG    (*TableMem)[]; /* */
  62.     WORD    EndTMem;    /* indice sur le dernier LONG occupé de TableMem */
  63.     WORD    GestFree;    /* dernier bloc de Gestion libre */
  64.     WORD    DataFree;    /* dernier bloc de Data libre */
  65.     LONG    *inCHIP;    /* Buffer 512L en CHIP pour TD */
  66.     struct  DiskList *disklist;    /* */
  67.     BYTE    Cli;    /* if non set, optimize for WB use */
  68.     BYTE    FLnoG;    /* if set, File List will no longuer be considered as Gestion B */
  69.     BYTE    Format; /* if set, the whole disk is formatted */
  70.     BYTE    Check;    /* if set, The Dos Structure of Source is Checked */
  71.     WORD    Err;    /* compteur d' erreur */
  72.     BYTE    DriveBusy[5];
  73. };
  74. struct var *VarAdr;
  75.  
  76. void RendMem(void);
  77. void FreeBusy(void);
  78.  
  79. main(ac,av)
  80. BYTE *av[];
  81. WORD ac;
  82. {
  83. WORD TotalBlocks,i,j=0,Perr=0;
  84. LONG k;
  85. BYTE argn;
  86.     puts("FO v1.3 Fast Optimizer by FBJ.");
  87.     VarAdr=(struct var *)AllocMem(sizeof(struct var),MEMF_CLEAR|MEMF_PUBLIC);
  88.     atexit(RendMem);
  89.  
  90.     WBench(1);                /* ( Par défault ) */
  91.     forFDir(0);
  92.     NoFormat(0);
  93.      Check(0);
  94.  
  95.     if (ac<3 )
  96.     {
  97.         if (*av[1]=='?') {help(); exit(0);}
  98.         else puts("? for help");exit(0);
  99.     }
  100.     if (strnicmp(av[1],"df",2)) {puts("1st arg: source drive"); exit(0);}
  101.     if (strnicmp(av[2],"df",2)) {puts("2nd arg: dest drive"); exit(0);}
  102.     sourceDrive=*(av[1]+2)-48;
  103.     destDrive=  *(av[2]+2)-48;
  104.     if (sourceDrive<0 || sourceDrive>3) {puts("1st arg: source drive"); exit(0);}
  105.     if (destDrive<0 || destDrive>3) {puts("2nd arg: dest drive"); exit(0);}
  106.  
  107.     argn=3;
  108.     while (ac>=argn && *av[argn]=='-')
  109.     {
  110.     switch (*(av[argn]+1)) {
  111.         case 'w' : WBench(1); break;
  112.         case 'W' : WBench(1); break;
  113.         case 'c' : ComLineInt(1); break;
  114.         case 'n' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break;
  115.         case 'N' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break;
  116.         case 'F' : if ( !strnicmp(av[argn]+1,"FDir",4) ) forFDir(1); break;
  117.         case 'C' : Check(1); break;
  118.         }
  119.     argn++;
  120.     }
  121.     
  122.  
  123.  
  124.     if (!OpenTD(sourceDrive)) {puts("Source drive Not Available"); exit(0);}
  125.     if (!OpenTD(destDrive)) {puts("Dest drive Not Available"); exit(0);}
  126.     atexit(CloseTD);
  127.  
  128.     puts("Now insert SOURCE disk and RETURN");
  129.     while ( (getchar()!=10 )) ;
  130.     DiskBUSY(av[2],1);
  131.     atexit(FreeBusy);
  132.     strncpy(drivebusy,av[2],5);
  133.     VarAdr->inCHIP=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  134.     VarAdr->BuffBitMap=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  135.     Read_WriteB(R,sourceDrive,BBM,880L); /* charge le Root */
  136.     /* on trouve BitMap */
  137.     VarAdr->BitMap=(WORD)((struct RootB *)(VarAdr->BuffBitMap))->BitMapTable[0]; 
  138. #ifdef DEBUG
  139.     printf("n ° du bloc BitMap :%d\n",VarAdr->BitMap);
  140. #endif
  141.     /* on le charge */
  142.     Read_WriteB(R,sourceDrive,BBM,VarAdr->BitMap);
  143.     /* on réserve le buffer de track et on charge le bootBlock oû il faut */
  144.     BT=(LONG *)AllocMem(11*512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  145.     Read_WriteB(R,sourceDrive,BT,0L);
  146.     Read_WriteB(R,sourceDrive,BT+128L,1L);
  147. #ifdef DEBUG
  148.     printf("Adr du Buff de Track : %p\n",BT);
  149. #endif
  150.     VarAdr->Empty=(LONG *)AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC);
  151.     if (VarAdr->Empty==0) Perr++;
  152.     VarAdr->TotalBlocks=HowBlockUsed(BBM);
  153. #ifdef DEBUG
  154.     printf("Total des Blocks Alloués : %d\n",VarAdr->TotalBlocks);
  155. #endif
  156.     VarAdr->TableMem=(APTR)AllocMem(VarAdr->TotalBlocks*4+4,MEMF_CLEAR|MEMF_PUBLIC);
  157. #ifdef DEBUG
  158.     printf("Adr de TableMem : %p\n",&VarAdr->TableMem);
  159. #endif
  160.     j=0;
  161.     for (i=0;i!=VarAdr->TotalBlocks;i++)
  162.     {
  163.     k=AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC);
  164.     if (k==0 || (AvailMem(MEMF_PUBLIC) < 20480)) {Perr=103; break;}
  165.     (*VarAdr->TableMem)[j++]=k;
  166.     }
  167.     (*VarAdr->TableMem)[j]=0L;
  168.     VarAdr->EndTMem=j-1;
  169.     
  170.     if (Perr)
  171.     {
  172.         puts("Sorry, No memory for Fast Optimizing");
  173.         exit(0);
  174.     }
  175.     /*    On initialise la strucure DiskList */
  176.     dsklist=(struct SinitB*)AllocMem(sizeof(struct SinitB),MEMF_CLEAR|MEMF_PUBLIC);
  177.     dsklist->dl_Bloc=-9;
  178.     ((struct SinitB*)dsklist)->dl_Type=0;
  179.  
  180.     /*    Avec un bloc initial qui ne sert à rien mais est bien pratique */
  181.  
  182.     LoadBinMem();
  183.     MtrOff(sourceDrive);
  184.     if (CHECK)
  185.     {
  186.         puts("Checking Dos Structure of disk");
  187.         CheckDosStruct();
  188.         if (!err) puts("No Error in Dos Structure");
  189.         else {printf("%d ERRORS on disk !! FO Stopped\n",err); exit(0);}
  190.     }
  191.     MtrOff(sourceDrive);
  192.     puts("Now I optimize ...");
  193.     Optimize();
  194.     BitMap();
  195.     ChangeBlocks();
  196.     puts("Writing result to destination disk");
  197.     MemToDisk();
  198.     puts("Fast Optimization done.");
  199.  
  200.     exit(0);
  201. }
  202.  
  203. void RendMem()
  204. {
  205. LONG    M=1;
  206. WORD    i=0;
  207.     if (VarAdr) {
  208.     if (VarAdr->BuffBitMap)
  209.     {
  210.         FreeMem(BBM,512L);
  211.         BBM=0L;
  212.     }
  213.     if (VarAdr->BuffTrack)
  214.     {
  215.         FreeMem(BT,11*512L);
  216.         BT=0L;
  217.     }
  218.     if (VarAdr->Empty)
  219.     {
  220.         FreeMem(VarAdr->Empty,512L);
  221.         VarAdr->Empty=0;
  222.     }
  223.     
  224.     i=0;
  225.     while (M)
  226.     {
  227.     M=(*VarAdr->TableMem)[i++];
  228.     if (M) FreeMem(M,512L); else break;
  229.     }
  230.     if (VarAdr->TableMem) FreeMem(VarAdr->TableMem,VarAdr->TotalBlocks*4+4);
  231.     if (dsklist) FreeDiskList();
  232.     if (VarAdr->inCHIP) {FreeMem(VarAdr->inCHIP,512L); VarAdr->inCHIP=0;}
  233.     }
  234.     if (VarAdr) {FreeMem(VarAdr,sizeof(struct var)); VarAdr=0;}
  235.  
  236. }
  237.  
  238. void FreeBusy()
  239. {
  240.     DiskBUSY(drivebusy,0);
  241. }
  242.  
  243. /*    isBlocUsed renvoie 1 si Block libre ou 0 si block occuppé 
  244.     il se réfère au BitMap    */
  245.  
  246. isBlocUsed(Bloc)
  247. WORD    Bloc;
  248. {
  249. LONG    A,B;
  250.     if (Bloc==0 || Bloc==1) return(1); /* Faux car blocks used mais pratique ! */
  251.     A=*(BBM+1+(Bloc-2)/32);
  252.     B=(A>>(((Bloc-2)%32)) & 0x1L);
  253.     return(B);     
  254. }
  255.  
  256. HowBlockUsed(AdrBM)
  257. LONG *AdrBM;
  258. {
  259. WORD i,TotalBlocks=0;
  260.  
  261.     for (i=2;i<=1760;i++)
  262.     {
  263.     TotalBlocks+=(WORD)!(isBlocUsed(i));
  264.     }
  265.     return(TotalBlocks);
  266. }
  267.  
  268. LoadBinMem()
  269. {
  270. LONG    n,m=0;
  271. APTR    buff1,buff2,inCHIP;
  272. struct DiskList *dlist;
  273.  
  274.     inCHIP=VarAdr->inCHIP;
  275.     puts("Reading Source and preparing for Fast Optimizing");
  276.     for (n=2;n<1760;n++)
  277.     {
  278.         if (isBlocUsed(n)==used) 
  279.         {
  280.             buff1=(APTR)(Buffer(m++));
  281.             if (TypeOfMem(buff1)&MEMF_CHIP) buff2=buff1;
  282.             else buff2=inCHIP;
  283.             if (Read_WriteB(R,(LONG)sourceDrive,buff2,n)) 
  284.             {
  285.                 puts("Read Error, can' t optimize");
  286.                 exit(0);
  287.             }
  288.             if (buff2==inCHIP) CopyMemQuick(buff2,buff1,512L);
  289. #ifdef DEBUG
  290.     if (!Buffer(m-1))
  291.     {
  292.         puts("Problème avec LoadBinMem !");
  293.         exit(0);
  294.     }
  295. #endif
  296.         Organising(buff1,dlist,n);
  297.         }        
  298.         if ((n%22)==0)
  299.         {
  300.             printf("CYL %d",n/22);
  301.             putchar(13);
  302.             fflush(stdout);
  303.         }
  304.         
  305.     }
  306.     
  307. }
  308.  
  309. /*    Cherche et renvoie l' adresse oû ranger le bloc */
  310. Buffer(m)
  311. LONG m;
  312. {
  313.     return((*VarAdr->TableMem)[m]);
  314. }
  315.  
  316. Organising(buff1,dlist,n)
  317. LONG    *buff1;
  318. LONG    n;
  319. struct DiskList *dlist;
  320.  
  321. {
  322.     switch (*buff1)
  323.     {
  324.         case 2L :
  325.         {
  326.             switch (*(buff1+127))
  327.             {
  328.  
  329.                 case 1L: /* RootBlock */
  330.                 {
  331.                 /*    printf("Type : RootB , bloc #%d\n",n);*/
  332.                     dlist=(struct DiskList *)Preparing(sizeof(struct SRootB),dsklist);
  333.                     dlist->dl_NextB=0;
  334.                     dlist->dl_Bloc=n;
  335.                     dlist->dl_Bloc2=n;
  336.                     dlist->dl_Data=0;
  337.                     dlist->dl_Type=3;
  338.                     dlist->dl_types.dl_type3.reserved1=0;
  339.                     dlist->dl_AdrB=buff1;
  340.                     break;
  341.                 }
  342.  
  343.                 case -3L: /* File Header Block */
  344.                 {
  345.                 /*    printf("Type : File HeaderB , bloc #%d\n",n);*/
  346.                     dlist=(struct DiskList *)Preparing(sizeof(struct SFileHderB),dsklist);
  347.                     dlist->dl_NextB=0;
  348.                     dlist->dl_Bloc=n;
  349.                     dlist->dl_Bloc2=0;
  350.                     dlist->dl_Type=-1;
  351.                     dlist->dl_types.dl_type1.dl_Parent=((struct FileHeaderB*)buff1)->ParentDir;
  352.                     dlist->dl_types.dl_type1.dl_NextHash=((struct FileHeaderB*)buff1)->NextHash;
  353.                     dlist->dl_types.dl_type1.dl_Extension=((struct FileHeaderB*)buff1)->Extension;
  354.                     dlist->dl_AdrB=buff1;
  355.                     dlist->dl_Data=isinfo(buff1);
  356.                     break;
  357.                 }
  358.  
  359.                 case 2L: /* User Directory Block */
  360.                 {
  361.                 /*    printf("Type : User DirB , bloc #%d\n",n);*/
  362.                     dlist=(struct DiskList *)Preparing(sizeof(struct SUserDirB),dsklist);
  363.                     dlist->dl_NextB=0;
  364.                     dlist->dl_Bloc=n;
  365.                     dlist->dl_Bloc2=0;
  366.                     dlist->dl_Type=4;
  367.                     dlist->dl_types.dl_type4.dl_Parent=((struct UserDirB*)buff1)->ParentDir;
  368.                     dlist->dl_types.dl_type4.dl_NextHash=((struct UserDirB*)buff1)->NextHash;
  369.                     dlist->dl_AdrB=buff1;
  370.                     dlist->dl_Data=isinfo(buff1);
  371.                     break;
  372.                 }
  373.  
  374.                 default :
  375.                 {
  376.                     printf("Type : UnknownB1 , bloc #%d\n",n); 
  377.                     dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist);
  378.                     dlist->dl_NextB=0;
  379.                     dlist->dl_Bloc=n;
  380.                     dlist->dl_Bloc2=n;
  381.                     dlist->dl_Data=0;
  382.                     dlist->dl_Type=-2;
  383.                     dlist->dl_AdrB=buff1; 
  384.                     break;
  385.                 }
  386.             }
  387.             break;
  388.         }
  389.  
  390.         case 16L: if (*(buff1+127)==-3) /* FileList Block */
  391.         {
  392.         /*    printf("Type : File ListB , bloc #%d\n",n);*/
  393.             dlist=(struct DiskList *)Preparing(sizeof(struct SFileListB),dsklist);
  394.             dlist->dl_NextB=0;
  395.             dlist->dl_Bloc=n;
  396.             dlist->dl_Bloc2=0;
  397.             dlist->dl_Data=0;
  398.             dlist->dl_Type=13;
  399.             dlist->dl_types.dl_type13.dl_FileHeader=((struct FileListB*)buff1)->ParentFH;
  400.             dlist->dl_types.dl_type13.dl_Extension=((struct FileListB*)buff1)->Extension;
  401.             dlist->dl_AdrB=buff1;
  402.             break;
  403.         }
  404.  
  405.         case 8L: /* Data Block */
  406.         {
  407. /*        printf("Type : DataB , bloc #%d\n",n);*/
  408.         dlist=(struct DiskList *)Preparing(sizeof(struct SDataB),dsklist);
  409.         dlist->dl_NextB=0;
  410.         dlist->dl_Bloc=n;
  411.         dlist->dl_Bloc2=0;
  412.         dlist->dl_Data=0;
  413.         dlist->dl_Type=8;
  414.         dlist->dl_types.dl_type8.dl_FileHeader=((struct DataB*)buff1)->HeaderKey;
  415.         dlist->dl_types.dl_type8.dl_NextData=((struct DataB*)buff1)->NextDataBlock;
  416.         dlist->dl_AdrB=buff1;
  417.         break;
  418.         }
  419.     
  420.         default :
  421.         {
  422. /*            printf("Type : UnknownB2 , bloc #%d\n",n); *//* Par ex le B BitMap */
  423.             if (n==VarAdr->BitMap) break;
  424.             dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist);
  425.             dlist->dl_NextB=0;
  426.             dlist->dl_Bloc=n;
  427.             dlist->dl_Bloc2=n;
  428.             dlist->dl_Data=0;
  429.             dlist->dl_Type=-2;
  430.             dlist->dl_AdrB=buff1;
  431.             break;
  432.         }
  433.     }
  434. }
  435.  
  436. Preparing(structsize,adr)
  437. LONG structsize;
  438. struct DiskList *adr;
  439.  
  440. {
  441. static struct DiskList *Sadr=0;
  442.  
  443.     if (Sadr==0) Sadr=adr; else adr=Sadr;
  444.     if (adr->dl_NextB==0)
  445.     {
  446.         adr->dl_NextB=(struct DiskList *)AllocMem(structsize,MEMF_PUBLIC);
  447.         if (adr->dl_NextB==0 || (AvailMem(MEMF_PUBLIC) < 20480))
  448.         {
  449.             if (adr->dl_NextB) {FreeMem(adr->dl_NextB,structsize);
  450.                 adr->dl_NextB=0;}
  451.             puts("No mem for Preparing()\nFree a few mem an retry");
  452.             exit(0);
  453.         }
  454.         Sadr=adr->dl_NextB;
  455.         return(adr->dl_NextB);
  456.     }
  457.     else return(Preparing(structsize,adr->dl_NextB));
  458. }
  459.  
  460. FreeDiskList()
  461. {
  462. struct DiskList *dlist;
  463. LONG    length=0;
  464. APTR    tmp;
  465.  
  466.     dlist=dsklist;
  467.     do
  468.     {
  469.         length=Length(dlist);
  470.         tmp=dlist->dl_NextB;
  471.         if (dlist && length) FreeMem(dlist,length); 
  472.         dlist=tmp;
  473.     }
  474.     while (dlist->dl_NextB!=0);
  475.     FreeMem(dlist,Length(dlist));    
  476.     dsklist=0;
  477.  
  478. }
  479.  
  480. Length(dlist)
  481. struct DiskList *dlist;
  482. {
  483. LONG length;
  484.     switch (dlist->dl_Type)
  485.     {
  486.         case -2L: length=sizeof(struct SUnknownB); break;
  487.         case 13L: length=sizeof(struct SFileListB); break;
  488.         case  8L: length=sizeof(struct SDataB); break;
  489.         case  4L: length=sizeof(struct SUserDirB); break;
  490.         case  3L: length=sizeof(struct SRootB); break;
  491.         case -1L: length=sizeof(struct SFileHderB); break;
  492.         case  0L: length=sizeof(struct SinitB); break;
  493.         default : length=0; puts("err in FreeDiskList"); break;
  494.     }
  495.     return(length);    
  496. }
  497.  
  498. CheckDosStruct()
  499. {
  500. struct DiskList *dlist;
  501. WORD n;
  502. struct RootB *adr;
  503.  
  504.     dlist=(APTR)whereB(880);
  505.     if (dlist==0) NotSet(880);
  506.     else
  507.  
  508.  
  509.     {    adr=(struct RootB *)dlist->dl_AdrB;
  510.         for (n=0;n<72;n++) /* 72 compris puisque n++ */
  511.         {
  512.             explore(adr->HashTable[n],880);
  513.         }
  514.     }
  515. }
  516.  
  517. /*    explore: suit une chaine de Hash à partir du bloc header en paramètre */
  518.  
  519. explore(bloc,parent)
  520. WORD bloc;
  521. WORD parent;
  522. {
  523. struct DiskList *dlist; 
  524. WORD n,nextbloc;
  525. struct UserDirB *adr;
  526.  
  527.     if (bloc==0) return(0);
  528.     /*printf("dans explore bloc: %d, parent: %d\n",bloc,parent);*/
  529.     dlist=VarAdr->disklist;
  530.     while (dlist->dl_Bloc!=bloc && dlist!=0)        dlist=dlist->dl_NextB;
  531.  
  532.     if (dlist==0) NotSet(bloc,parent);
  533.     else
  534.  
  535.     if (dlist->dl_Type!=-1 && dlist->dl_Type!=4)
  536.     {
  537.         printf ("ERR : Block #%d SHOULD BE Header or UserDir block\n",bloc);
  538.         err++;
  539.     }
  540.  
  541.     if (dlist->dl_types.dl_type4.dl_Parent!=parent)
  542.     {
  543.         printf("ERR : Link Error between block #%d and #%d\n",bloc,parent);
  544.         err++;
  545.     }
  546.  
  547.     if (dlist->dl_Type==-1) CheckHeader(dlist);
  548.     if (dlist->dl_Type==4) 
  549.     {
  550.         adr=(struct UserDirB *)dlist->dl_AdrB;
  551.         for (n=0;n<72;n++)
  552.         {
  553.             explore(adr->HashTable[n],bloc);    
  554.         }
  555.     }
  556.  
  557.     if (nextbloc=dlist->dl_types.dl_type1.dl_NextHash==0) return(0);
  558.     else explore(nextbloc,parent);
  559. }
  560.  
  561. CheckHeader(dlist)
  562. struct DiskList *dlist;
  563. {
  564. WORD bloc,n;
  565. struct FileHeaderB *adr;
  566. BYTE errfile=0;
  567.  
  568.     bloc=dlist->dl_Bloc;
  569.     /*printf("dans CheckHeader bloc: %d\n",bloc);*/
  570.     adr=dlist->dl_AdrB;
  571.  
  572.     for (n=0;n<72;n++)
  573.     {
  574.         errfile+=CheckLink(adr->DataTable[n],bloc);
  575.     }
  576.     if (adr->Extension) CheckFList(adr->Extension,bloc);
  577.  
  578.  
  579.     if (errfile) badFile(adr->FileName);
  580.     return(0);
  581. }
  582. CheckFList(bloc,fhb)
  583. WORD bloc,fhb;
  584. {
  585. struct SFileListB *dlistFL;
  586. struct FileListB  *adr;
  587. BYTE   errfile=0;
  588. WORD   n;
  589.  
  590.     dlistFL=(APTR)whereB(bloc);
  591. /*    printf("dans CheckFList bloc: %d, pour FHB: %d\n",bloc,fhb);*/
  592.     if (dlistFL==0) NotSet(bloc,fhb);
  593.     else{
  594.     if (dlistFL->dl_Type!=13)
  595.     {
  596.         printf ("ERR : Block #%d SHOULD BE FileList block\n",bloc);
  597.         err++;
  598.         errfile++;
  599.     }
  600.     else
  601.     {
  602.         adr=(struct FileListB *)dlistFL->dl_AdrB;
  603.         if (adr->ParentFH!=fhb)
  604.         {
  605.             printf("ERR : Link Error between block #%d and #%d\n",bloc,fhb);
  606.             err++;
  607.         }
  608.         for (n=0;n<72;n++)
  609.         {
  610.             errfile+=CheckLink(adr->DataTable[n],fhb);
  611.         }
  612.     }
  613.     if (adr->Extension) errfile+=CheckFList(adr->Extension,fhb);
  614.     }
  615.     return(errfile);
  616. }
  617.  
  618. CheckLink(dataB,fhB)
  619. WORD dataB,fhB;
  620. {
  621. struct SDataB *dlist;
  622. BYTE errdata=0;
  623.  
  624.     if (dataB==0) return(0);
  625. /*    printf("dans CheckLink data : %d, fh : %d\n",dataB,fhB);*/
  626.     dlist=(struct SDataB *)VarAdr->disklist;
  627.     while (dlist->dl_Bloc!=dataB && dlist!=0)        dlist=dlist->dl_NextB;
  628.  
  629.     if (dlist==0) NotSet(dataB,fhB);
  630.     else
  631.  
  632.     if (dlist->dl_Type!=8)
  633.     {
  634.         printf ("ERR : Block #%d SHOULD BE data block (pointed by FHB #%d)\n",dataB,fhB);
  635.         err++;
  636.         errdata=1;
  637.     }
  638.     else
  639.     if (dlist->dl_type8.dl_FileHeader!=fhB)
  640.     {
  641.         printf("ERR : Link Error between block #%d and #%d\n",fhB,dataB);
  642.         err++;
  643.         errdata=1;
  644.     }
  645.     return(errdata);
  646. }
  647.  
  648. badFile(adrName)
  649. BYTE *adrName;
  650. {
  651. BYTE length;
  652. BYTE buff[30];
  653.  
  654.     length=*adrName;
  655.     adrName++;
  656.     strncpy(buff,adrName,length);
  657.     buff[length]=0;
  658.     printf("File %s contains errors\n",buff);
  659. }
  660.  
  661. NotSet(bloc,where)
  662. WORD bloc,where;
  663. {
  664.     printf("Block #%d Not Found ! (not unset in BitMap), in %p\n",bloc,where);
  665.     err++;
  666. }
  667.  
  668. whereB(bloc)
  669. WORD bloc;
  670. {
  671. struct DiskList *dlist;
  672.  
  673.     dlist=VarAdr->disklist;
  674.     while (dlist->dl_Bloc!=bloc && dlist!=0) dlist=dlist->dl_NextB;
  675.     return(dlist);
  676. }
  677. isinfo(buff)
  678. BYTE *buff;
  679. {
  680. BYTE name[30],length,n;
  681.  
  682.  
  683.     length=buff[108*4];
  684.     strncpy(name,buff+108*4+1,length);
  685.     name[length]=0;
  686.     for (n=length; n>=0 && name[n] != '.';n--);
  687.     if (stricmp(name+n,".info")==0)
  688.     return(1); 
  689.     else return(0);
  690. }
  691.  
  692. Optimize()
  693. {
  694. WORD UDB[100];
  695. WORD i=1;
  696.  
  697.     UDB[0]=880;
  698.     UDB[1]=0;
  699.     /*printf("UDB[0] : %d\n",UDB[0]);*/
  700.     while (UDB[0])
  701.     {if (!arrange(UDB,&i)) break;} 
  702.  
  703. }
  704.  
  705. arrange(UDB,i)
  706. WORD UDB[],*i;
  707. {
  708. static WORD gfree=882,dfree=2;
  709. struct SUserDirB *udbf,*udbp,*fhB;
  710. struct UserDirB  *adrf;
  711. struct UserDirB  *adrp;
  712. /*struct DiskList     *hdb;*/
  713. struct FileHeaderB *adrh;
  714. WORD   UDBP,n,bloc,parent;
  715.  
  716. /*    printf("in arrange() UDB[0] : %d, i : %d\n",UDB[0],*i);*/
  717.     udbf=(APTR)whereB(UDB[0]);
  718.     if (udbf==0) {NotSet(UDB[0],0); return(0);}
  719.  
  720.     for (n=0;n<*i;n++) UDB[n]=UDB[n+1];    /* On s' occuppe de UDB[0] donc on le retire de la liste */
  721.     UDB[*i]=0;
  722.     (*i)--;
  723.  
  724.     UDBP=udbf->dl_type4.dl_Parent;
  725.  
  726.     if (UDBP)    /* null si Root */
  727.     {
  728.         udbp=(APTR)whereB(UDBP);
  729.         if (udbp==0) {NotSet(UDBP,1); return(0);}
  730.     }
  731.  
  732.     adrf=udbf->dl_AdrB;
  733.     /*printf("adrf : %p\n",adrf);*/
  734.  
  735.     if (UDBP)    /* Cas du User Dir B */
  736.     {
  737.         adrp=udbp->dl_AdrB;
  738.         parent=adrf->ParentDir=udbp->dl_Bloc;    /* Les Parents sont tjs déplacés avt */
  739.     }
  740.  
  741.     for (n=71;n!=-1;n--)
  742.     {
  743.     
  744.         bloc=adrf->HashTable[n];
  745.         if (bloc)
  746.         {
  747.             adrf->HashTable[n]=gfree;
  748.             do
  749.             {
  750.                 fhB=(APTR)whereB(bloc);
  751.                 if (fhB==0) {NotSet(bloc,2); break;}
  752.  
  753.                 if (fhB->dl_Type==-1)
  754.                 {
  755.                     gfree=MoveHderB(bloc,gfree,&dfree,UDB,i);
  756.                 }
  757.                 else
  758.                 if (fhB->dl_Type==4)
  759.                 {
  760.                     gfree=MoveUserDirB(bloc,gfree,parent);
  761.                     UDB[(*i)++]=bloc;
  762.                     UDB[*i]=0;
  763.                 }
  764.  
  765.                 adrh=(struct FileHeaderB *)fhB->dl_AdrB;
  766.                 bloc=adrh->NextHash;
  767.                 adrh->NextHash= (bloc ? gfree : 0);
  768.                 /*printf("adrh: %p,bloc: %d\n",adrh,bloc);*/
  769.             }
  770.             while (bloc);
  771.         }
  772.     }
  773.     /*printf("gfree: %d dfree: %d\n",gfree,dfree);*/
  774.     GFree=gfree;
  775.     DFree=dfree;
  776.     return(1);
  777. }
  778.  
  779.  
  780.  
  781.  
  782. Inc(datafree)
  783. WORD *datafree;
  784. {
  785. #ifdef DEBUG
  786. /*    printf("in Inc() datafree: %d\n",*datafree);*/
  787. #endif
  788.     if (*datafree<879) (*datafree)++; /* Ainsi 879 est donné mais pas 880 */
  789.     else
  790.     {
  791.         if (*datafree==879) *datafree=1759;
  792.         else (*datafree)--;
  793.     }
  794.     return(*datafree);
  795. }
  796.  
  797. Nextdfree(datafree)
  798. WORD *datafree;
  799. {
  800.     if (*datafree<879) return(*datafree+1); 
  801.     else
  802.     {
  803.         if ((*datafree+1)==880) return(1759);
  804.         else return(*datafree-1);
  805.     }
  806. }
  807.  
  808. /*    MoveHderB déplace le Header spécifié du bloc lB au bloc nB.
  809.     nB: nouveau n° de bloc.
  810.     oB: ancien  n° de bloc.
  811. */
  812.  
  813. MoveHderB(oB,nB,datafree,UDB,i)
  814. WORD nB,oB,*datafree;
  815. WORD UDB[],*i;
  816. {
  817. struct SFileHderB *dlistB,*fhB;
  818. struct FileHeaderB *adr;
  819. struct DiskList     *hdb;
  820. struct FileHeaderB *adrh;
  821. WORD   n,ret,ext,bloc,*nflB;
  822. WORD   gfree;
  823. LONG   AdrD;
  824. BYTE   first;
  825. #ifdef DEBUG
  826.     printf("in MoveHderB() oB: %d, nB: %d,datafree: %d\n",oB,nB,*datafree);
  827. #endif
  828.     dlistB=(APTR)whereB(oB);
  829.     if (dlistB==0) NotSet(oB,4);
  830.     else
  831.     {
  832.         if (dlistB->dl_Type!=-1) return(0);
  833.         adr=(struct FileHeaderB *)dlistB->dl_AdrB;
  834.             /* On change le HeaderKey du bloc */
  835.         adr->HeaderKey=nB;
  836.         dlistB->dl_Bloc2=nB;
  837.  
  838.             /* On change tous les DatasB en conséquence */
  839.         gfree=nB+1;
  840.         first=1;
  841.  
  842.         for (n=71;n!=-1;n--)
  843.         {    
  844.             if (adr->DataTable[n])
  845.             {
  846.                 if ( (dlistB->dl_Data==1) && (CLI==0) ) /* bloc de data ds gestion */
  847.                 {
  848.                     AdrD=ModifyDataHder(adr->DataTable[n],nB,gfree,adr);
  849.                     adr->DataTable[n]=gfree;
  850.                     if (first) {adr->FirstDataB=gfree; first=0;}
  851.  
  852.                     gfree++;
  853.                     if (n) ModifyDataNext(AdrD,gfree);
  854.                     else ModifyDataNext(AdrD,gfree+1);
  855.                 }
  856.                 else
  857.                 {
  858.                     AdrD=ModifyDataHder(adr->DataTable[n],nB,*datafree,adr);
  859.                     adr->DataTable[n]=*datafree;
  860.                     if (first) {adr->FirstDataB=*datafree; first=0;}
  861.  
  862.                     Inc(datafree);
  863.                     if (n) ModifyDataNext(AdrD,*datafree);
  864.                     else
  865.                     {
  866.                         if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree));
  867.                         else ModifyDataNext(AdrD,*datafree);
  868.                     }
  869.                 }
  870.  
  871.             }
  872.         }
  873.  
  874.         if (adr->Extension) 
  875.         {
  876.             if (FLnog) 
  877.             {
  878.                 nflB=datafree;
  879.                 ext=*datafree;
  880.             }    
  881.             else
  882.             {
  883.                 nflB=&gfree;
  884.                 ext=gfree;
  885.             }
  886.             if (CLI)    /* pas de .info dans les blocs de gestion */
  887.             {
  888.                 ModifyFList(adr->Extension,nB,nflB,datafree,0);
  889.             }
  890.             else
  891.             if (dlistB->dl_Data==1) /* si .info alors ds les blocs de gestion */
  892.             {
  893.                 ModifyFList(adr->Extension,nB,nflB,&gfree,1);
  894.             }
  895.             else
  896.             {
  897.                 ModifyFList(adr->Extension,nB,nflB,datafree,0);
  898.             }
  899.             adr->Extension=ext;
  900.         }
  901.  
  902.  
  903.     }
  904.     return(gfree);
  905. }
  906.  
  907. ModifyDataHder(bloc,nfhB,ndataB,adrfh)
  908. WORD bloc,nfhB,ndataB;
  909. LONG adrfh;
  910. {
  911. struct SDataB *dlistD;
  912. struct DataB  *adr;
  913.  
  914. #ifdef DEBUG
  915.     printf("in MofifyDataHder() bloc: %d, nfhB : %d, ndataB: %d\n",bloc,nfhB,ndataB);
  916. #endif
  917.     dlistD=(APTR)whereB(bloc);
  918.     if (dlistD==0) {NotSet(bloc,adrfh); exit(0);}
  919.     else
  920.     dlistD->dl_Bloc2=ndataB;
  921.     dlistD->dl_type8.dl_FileHeader=nfhB;
  922.     adr=dlistD->dl_AdrB;
  923.     adr->HeaderKey=nfhB;
  924.     return(adr);
  925. }
  926.  
  927. ModifyDataNext(adr,ndataNext)
  928. WORD ndataNext;
  929. struct DataB *adr;
  930. {
  931.     if (adr->NextDataBlock)    adr->NextDataBlock=ndataNext;
  932.  
  933. }
  934.  
  935. /* Renvoie n° du prochain bloc libre */
  936.  
  937. ModifyFList(bloc,nfhB,nflB,datafree,data)
  938. WORD bloc,nfhB,*nflB,*datafree,data;
  939. {
  940. struct SFileListB *dlistFL;
  941. struct FileListB  *adr;
  942. LONG   *AdrD;
  943. WORD   n,ret=0,ext;
  944. BYTE   first;
  945. #ifdef DEBUG
  946.     printf("in MofifyFList() bloc: %d, nfhB : %d, nflB: %d,datafree: %d\n",bloc,nfhB,*nflB,(*datafree)+1);
  947. #endif
  948.     dlistFL=(APTR)whereB(bloc);
  949.     if (dlistFL==0) NotSet(bloc,5);
  950.     else
  951.     {
  952.         /*printf(" Type du bloc: %d\n",dlistFL->dl_Type);*/
  953.         dlistFL->dl_type13.dl_FileHeader=nfhB;
  954.         dlistFL->dl_Bloc2=*nflB;
  955.         adr=(struct FileListB *)dlistFL->dl_AdrB;
  956.         adr->ParentFH=nfhB;
  957.         adr->HeaderKey=*nflB;
  958.         if (FLnog) Inc(nflB); else (*nflB)++;
  959.         
  960.         first=1;
  961.         for (n=71;n!=-1;n--)
  962.         {
  963.             if(adr->DataTable[n])
  964.             {
  965.                 AdrD=(APTR)ModifyDataHder(adr->DataTable[n],nfhB,*datafree,bloc);
  966.                 adr->DataTable[n]=*datafree;
  967.                 if (first) {adr->FirstDataB=*datafree; first=0;}
  968.  
  969.                 if (data==0) Inc(datafree); else (*datafree)++;
  970.  
  971.                 if (n)
  972.                 {
  973.                     if (data==0) ModifyDataNext(AdrD,*datafree);
  974.                     else ModifyDataNext(AdrD,*datafree+1);
  975.                 }
  976.                 else
  977.                 {
  978.                     if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree));
  979.                     else ModifyDataNext(AdrD,*datafree);
  980.                 }
  981.             }
  982.         }
  983.  
  984.         ext=*nflB;
  985.         if (adr->Extension) 
  986.         {
  987.             ret+=ModifyFList(adr->Extension,nfhB,nflB,datafree,data);
  988.             adr->Extension=ext;
  989.             return(++ret);
  990.         }
  991.  
  992.         return(ext);
  993.     }
  994. }
  995.  
  996. MoveUserDirB(oB,nB,parent)
  997. WORD oB,nB,parent;
  998. {
  999. struct SUserDirB *dlist;
  1000. struct UserDirB *adr;
  1001. WORD n;
  1002.  
  1003. #ifdef DEBUG
  1004.     printf("in MoveUserDir() oB: %d, nB: %d, parent: %d\n",oB,nB,parent);
  1005. #endif
  1006.     dlist=(APTR)whereB(oB);
  1007.     if (dlist==0) NotSet(oB,6);
  1008.     else
  1009.     {    
  1010.         if (dlist->dl_Type==4)
  1011.         {
  1012.  
  1013.             adr=dlist->dl_AdrB;
  1014.             dlist->dl_Bloc2=nB;
  1015.             adr->HeaderKey=nB;
  1016.             for (n=71;n!=-1;n--)
  1017.             {
  1018.                 if (adr->HashTable[n])
  1019.                 {
  1020.                     MoveHashFils(adr->HashTable[n],nB);
  1021.                 }
  1022.             }
  1023.         return(nB+1);
  1024.         } else puts("err in MoveUserDirB");
  1025.     }
  1026. }
  1027.  
  1028. MoveHashFils(bloc,parent)
  1029. WORD bloc,parent;
  1030. {
  1031. struct DiskList *dlist;
  1032. struct  FileHeaderB *adr;
  1033.  
  1034. #ifdef DEBUG
  1035.     printf("in MoveHashFils() bloc: %d, parent: %d\n",bloc,parent);
  1036. #endif
  1037.     do
  1038.     {
  1039.     dlist=(APTR)whereB(bloc);
  1040.     if (dlist==0) {NotSet(bloc,7); return(0);}
  1041.     adr=dlist->dl_AdrB;
  1042.     dlist->dl_types.dl_type4.dl_Parent=parent;
  1043.     adr->ParentDir=parent;
  1044.     bloc=adr->NextHash;
  1045.     }
  1046.     while (bloc);
  1047. }
  1048.  
  1049. ChangeBlocks()
  1050. {
  1051. struct DiskList *dlist;
  1052.  
  1053.     dlist=(struct DiskList *)VarAdr->disklist;
  1054.  
  1055.     while (dlist) 
  1056.     {
  1057.         dlist->dl_Bloc=dlist->dl_Bloc2;
  1058.         dlist=dlist->dl_NextB;
  1059.     }
  1060.  
  1061. }
  1062.  
  1063. MemToDisk()
  1064. {
  1065. WORD n,bitmap;
  1066. LONG offset,*adrB,*empty,ddrive,A;
  1067. BYTE *BuffT,write,length;
  1068. WORD c,Form;
  1069. struct DiskList *dlist=0;
  1070. struct RootNode *RN;
  1071. struct RootB *adr;
  1072.  
  1073.     if (sourceDrive==destDrive) {puts("Now insert dest disk and RETURN");
  1074.     while ( (c=getchar()) != 10) ;}
  1075.  
  1076.     if (isInserted(destDrive)) {puts("YOU MUST insert DESTINATION disk and RETURN");
  1077.     while ( (c=getchar()) != 10) ;
  1078.     while (isInserted(destDrive)) fflush(stdout); }
  1079.  
  1080.     if (isProtected(destDrive)) {puts("UnProtect DESTINATION disk and press RETURN");
  1081.     while ( (c=getchar()) != 10) ;
  1082.     while (isProtected(destDrive)) fflush(stdout);}
  1083.     
  1084.  
  1085.     offset=2*512L;    /* Le boot Block est déja dans le Buffer de Track */
  1086.     BuffT=BT;
  1087.     /*    On met à jour la date de dernière modif de la disquette */
  1088.     dlist=(APTR)whereB(880);
  1089.     if (dlist==0) NotSet(880,8);
  1090.     adr=dlist->dl_AdrB;
  1091.     RN=(struct RootNode *)(DOSBase->dl_Root);
  1092.     adr->Mday=RN->rn_Time.ds_Days;
  1093.     adr->Mmin=RN->rn_Time.ds_Minute;
  1094.     adr->Mtick=RN->rn_Time.ds_Tick;
  1095.  
  1096.     length=adr->DiskName[0];
  1097.     adr->DiskName[0]=length+1;
  1098.     if (length<30) adr->DiskName[length+1]='.';
  1099.     else {adr->DiskName[length]='.'; adr->DiskName[0]=length;}
  1100.  
  1101.     bitmap=VarAdr->BitMap;
  1102.     empty=VarAdr->Empty;
  1103.     ddrive=destDrive;
  1104.     A=('F'<<24|'B'<<16|'J'<<8|'.');
  1105.  
  1106.     for (n=0;n<128;n++)
  1107.     {
  1108.         empty[n]=A;
  1109.     }
  1110.  
  1111.     /*printf("buffer a l' adresse %p\n",empty);*/
  1112.     putchar(13);
  1113.  
  1114.     Form=FORMAT;
  1115.     /*printf("Form : %d, VarAdr->Format: %ld\n",Form,VarAdr->Format);*/
  1116.     write=Form;
  1117.     for (n=2;n<1761;n++)
  1118.     {
  1119.         if (offset==11*512) 
  1120.         {
  1121.             /*printf("(n-12): %d\n",(n-11));    */
  1122.             if (write)    CMDonD(ddrive,TD_FORMAT,0,11*512L,BuffT,(n-11)*512L);
  1123.             offset=0L;
  1124.             if (!Form) write=0;
  1125.         }
  1126.         if (( (n-22) % 22 )==0)
  1127.         {
  1128.             printf("CYL n°: %d",n/22);
  1129.             putchar(13);
  1130.             fflush(stdout);
  1131.         }
  1132.         if (n==881) {adrB=BBM; write=1;}
  1133.         else 
  1134.         {
  1135.             dlist=(APTR)whereB(n);
  1136.             if (dlist==0) adrB=empty;
  1137.             else 
  1138.             {
  1139.                 adrB=dlist->dl_AdrB;
  1140.                 BuildCheckSum(adrB);
  1141.                 write=1;
  1142.             }
  1143.         }    
  1144.         CopyMemQuick(adrB,BuffT+offset,512L);
  1145.         offset+=512L;
  1146.     }
  1147.  
  1148. BuildCheckSum(Buffer)
  1149. ULONG *Buffer;
  1150. {
  1151. ULONG B;
  1152. WORD    n;
  1153.     
  1154.     Buffer[5]=0;
  1155.     n=0;
  1156.     B=0;
  1157.     while (n<=127)
  1158.     {
  1159.         B+=Buffer[n]; 
  1160.         n++;
  1161.     }
  1162.     Buffer[5]=-B;
  1163. }
  1164.  
  1165. BitMap()
  1166. {
  1167. struct DiskList *dlist;
  1168. struct RootB *adr;
  1169. WORD     n;
  1170. LONG    *buffbm,SBM=0;
  1171.  
  1172.     buffbm=BBM;
  1173.     dlist=(APTR)whereB(880);
  1174.     if (dlist==0) NotSet(880,9);
  1175.  
  1176.     adr=dlist->dl_AdrB;
  1177.     adr->BitMapTable[0]=881L;
  1178.     adr->BMvalid=-1;
  1179.  
  1180.     /*printf("GFree: %d DFree: %d\n",GFree,DFree);*/
  1181.  
  1182.     for (n=0;n!=56;n++) buffbm[n]=-1L;    /* on nettoye le BitMap */
  1183.     for (n=56;n!=128;n++) buffbm[n]=0L;
  1184.     if (DFree<880)
  1185.     {
  1186.         for (n=0;n<DFree;n++) SetBinBM(n,buffbm);
  1187.     }
  1188.     else
  1189.     {
  1190.         for (n=0;n!=880;n++) SetBinBM(n,buffbm);
  1191.         for (n=DFree+1;n!=1761;n++) SetBinBM(n,buffbm);
  1192.         
  1193.     }
  1194.  
  1195.     for (n=880;n!=GFree;n++) SetBinBM(n,buffbm);
  1196.  
  1197.     buffbm[0]=0L;
  1198.     for (n=0;n!=128;n++)
  1199.     {
  1200.         SBM+=buffbm[n];
  1201.     }
  1202.     buffbm[0]=-SBM;
  1203.  
  1204. }
  1205.  
  1206. SetBinBM(bloc,adrbm)
  1207. WORD bloc;
  1208. LONG *adrbm;
  1209. {
  1210.     adrbm++;
  1211.     adrbm[(bloc-2)/32] &= ~(1<< ( (bloc-2)%32 ));
  1212. }
  1213.  
  1214. /* Les options. */
  1215.  
  1216. WBench(flag)
  1217. BYTE flag;
  1218. {
  1219.     CLI=!flag;
  1220. /*    printf("in WBench, CLI set to %d\n",!flag);*/
  1221. }
  1222.  
  1223. ComLineInt(flag)
  1224. BYTE flag;
  1225. {
  1226.     CLI=flag;
  1227. /*    printf("in ComLineInt, CLI set to %d\n",flag);*/
  1228. }
  1229.  
  1230. NoFormat(flag)
  1231. BYTE flag;
  1232. {
  1233.     VarAdr->Format=!flag;
  1234. /*    printf("in NoFormat, Format set to %d\n",VarAdr->Format);*/
  1235. }
  1236.  
  1237. forFDir(flag)
  1238. BYTE flag;
  1239. {
  1240.     FLnog=flag;
  1241. /*     printf("in forFDir, FLnog set to %d\n",flag);*/
  1242. }
  1243.  
  1244. Check(flag)
  1245. BYTE flag;
  1246. {
  1247.     CHECK=flag;
  1248. }
  1249.  
  1250. help()
  1251. {
  1252.     puts("FO is FreeWare but contributions are welcomed: ");
  1253.     puts("");
  1254.     puts("Send any donations to CAMPAGNE Fabien");
  1255.     puts("                      805,  Rue des Gentianes");
  1256.     puts("                      39000 Lons Le Saunier");
  1257.     puts("                      France");
  1258.     puts("");
  1259.     puts("Now how to use FO:");
  1260.     puts("          1st argument must be SOURCE drive");
  1261.     puts("          2nd argument must be DESTINATION drive");
  1262.     puts("                        (They could be equal)");
  1263.     puts("Options:");
  1264.     puts("          -w : Worbench optimization ( all .info files (ex disk.info) are");
  1265.     puts("                near gestion-blocks)");
  1266.     puts("          -c : CLI optimization ( .info files are in the area of data-blocks)");
  1267.     puts("          -nFo or -nFormat if you use disk already formatted on destination.");
  1268.     puts("          -C : Check of the Dos Structure of Source disk before optimization.");
  1269.     puts("          -FDir : to use in conjunction with FDir (the Fast Dir by mine)");
  1270.     puts("                  (File List blocks are moved in data-area)");
  1271.     puts("");
  1272.     puts("                                 Enjoy FO.           FBJ.");
  1273. }
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.